<?php

namespace app\common\service\ai;

use app\common\service\system\UserService;
use SimpleXMLElement;
use think\facade\Db;
use think\facade\Log;

class WxPayService {

    static function GetPayParam($openid, $amount, $orderNo):array{
        $appId = env('WX.WX_PAY_APPID');
        $mchId = env('WX.WX_PAY_MCHID');
        $key = env('WX.WX_PAY_KEY');
        $notifyUrl = env('WX.WX_PAY_NOTIFY_URL');

        $nonceStr = self::generateNonceStr();
        $timeStamp = time();

        $data = [
            'appid' => $appId,
            'mch_id' => $mchId,
            'nonce_str' => $nonceStr,
            'body' => '1234',
            'out_trade_no' => $orderNo,
            'total_fee' => $amount*100,
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
            'notify_url' => $notifyUrl,
            'trade_type' => 'JSAPI',
            'openid' => $openid,
        ];

        // 签名
        $data['sign'] = self::generateSign($data, $key);
        // 将数据转为XML
        $xmlData = self::arrayToXml($data);
        // 发起请求
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $response = self::postXml($url, $xmlData);
        // 解析响应
        $result = self::xmlToArray($response);

//        //测试参数
//        $prepayId="2342342";
//        return [
//            'appId' => $appId,
//            'timeStamp' => (string)$timeStamp,
//            'nonceStr' => $nonceStr,
//            'package' => "prepay_id={$prepayId}",
//            'signType' => 'MD5',
//            'paySign' => self::generateSign([
//                'appId' => $appId,
//                'timeStamp' => (string)$timeStamp,
//                'nonceStr' => $nonceStr,
//                'package' => "prepay_id={$prepayId}",
//                'signType' => 'MD5'
//            ], $key),
//        ];


        if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
            // 获取预支付ID
            $prepayId = $result['prepay_id'];
            return [
                'appId' => $appId,
                'timeStamp' => (string)$timeStamp,
                'nonceStr' => $nonceStr,
                'package' => "prepay_id={$prepayId}",
                'signType' => 'MD5',
                'paySign' => self::generateSign([
                    'appId' => $appId,
                    'timeStamp' => (string)$timeStamp,
                    'nonceStr' => $nonceStr,
                    'package' => "prepay_id={$prepayId}",
                    'signType' => 'MD5'
                ], $key),
            ];
        } else {
            exception($result["err_code_des"]);
        }

    }

    // 生成随机字符串
    static function generateNonceStr($length = 32) {
        return bin2hex(random_bytes($length / 2));
    }

    // 生成签名
    static function generateSign($data, $key) {
        ksort($data);
        $string = '';
        foreach ($data as $k => $v) {
            $string .= "{$k}={$v}&"; // 手动构建字符串，保持原样
        }
        $string .= "key={$key}";
        return strtoupper(md5($string));
    }

    // XML 转数组
    static function xmlToArray($xml) {
        // 去除多余的空格和换行
        $xml = trim($xml);

        // 加载 XML 字符串并转为对象
        $simpleXml = simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA);

        // 检查是否成功加载
        if ($simpleXml === false) {
            return []; // 或抛出异常
        }

        // 转换为 JSON 然后再为数组
        return json_decode(json_encode($simpleXml), true);
    }


    // 数组转 XML
    static function arrayToXml($data) {
        $xml = new SimpleXMLElement('<xml/>');
        foreach ($data as $key => $value) {
            $xml->addChild($key, $value);
        }
        return $xml->asXML();
    }

    // POST XML
    static function postXml($url, $xmlData) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlData);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: text/xml']);

        // 处理 SSL 证书问题（调试时使用）
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

        $response = curl_exec($ch);

        if ($response === false) {
            return false;
        }

        curl_close($ch);
        return $response;
    }


    public function handleWeChatPayCallback($xml): string
    {
        $key = env('WX_PAY_KEY');
        $data = $this->xmlToArray($xml);
        Log::record('签名: ' . json_encode($data), 'info');
        if (empty($data) || !isset($data['return_code']) || $data['return_code'] !== 'SUCCESS') {
            // 处理解析失败或返回码不是 SUCCESS 的情况
            http_response_code(400);
            return "Invalid data";
        }

        // 进行签名验证
//        if (!$this->validateSignature($data, $key)) {
//            // 签名验证失败
//            return "Signature validation failed";
//        }

        // 处理支付结果
        $billNo = $data['out_trade_no'];
        $transactionId = $data['transaction_id'];
        $totalFee = $data['total_fee'];

        $bill = BillService::getDetail($billNo);
        if($bill['status'] == 0){
            $billData = [
                'bill_no' => $billNo,
                'transaction_id' => $transactionId,
                'total_fee' => $totalFee,
                'status'=>1
            ];
            BillService::saveBill($billData);

            // 订单支付回调
            OrderService::callback($bill['order_no']);
        }

        // 成功响应
        return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
    }

    private function validateSignature($data, $key) {
        unset($data['sign']);

        ksort($data);
        $string = http_build_query($data) . "&key={$key}";

        $calculatedSign = strtoupper(md5($string));

        return $calculatedSign === $data['sign'];
    }

}
